﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using CCSManager.CCS;
using Infragistics.Windows.Chart;

namespace CCSManager
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Dashboard : Window
    {
        private Products newProductReg;
        private Border overlay;
        private Random r;
        private List<DeveloperApplication> products = new List<DeveloperApplication>();

        public Dashboard()
        {
            InitializeComponent();
            Closed += Dashboard_Closed;
            ReloadProductTable();
        }

        void ReloadProductTable()
        {
            Cursor lastCursor = this.Cursor;
            try
            {
                this.Cursor = Cursors.Wait;
                var ccs = new CCS.CCS();
                products = new List<DeveloperApplication>();
                foreach (Guid devToken in App.DeveloperTokens)
                {
                    #region Fakeness

#if DEBUG
                    // Let's make sure that we have some registrations
                    // for our app when testing
                    var prods = ccs.GetProducts(devToken);
                    foreach (var prod in prods)
                    {
                        ccs.RegisterUser("Doe", "John", "114 Alaskan Way", "Seattle", "WA", "98201", "206-555-1234", "johndoe@iaspace.com", devToken.ToString(), prod.Name, Guid.NewGuid().ToString(), "Shareware");
                    }
#endif

                    #endregion

                    products.AddRange(ccs.GetProducts(devToken));
                }

                foreach (AppStatusRow row in addedRows)
                {
                    AppStatusGrid.Children.Remove(row);
                    if (AppStatusGrid.RowDefinitions.Count > 1)
                    {
                        AppStatusGrid.RowDefinitions.RemoveAt(1);
                    }
                }

                addedRows = new List<AppStatusRow>();

                CombinedRevenueOverTimeChart.Series.Clear();
                CombinedInstallationsOverTimeChart.Series.Clear();

                int rowIndex = 1;

                var rgbRand = new Random(DateTime.Now.Second);
                int ctr = 0;
                foreach (var product in products)
                {
                    var aps = new AppStatus { AppName = product.Name, ID = product.ID };

                    #region Fakeness

#if DEBUG
                    // Let's make sure that our app has some
                    // sales history going back a few months
                    // TODO: This needs to be aggregated from real data
                    aps.AppSalesData = new List<AppSalesData>
                                           {
                                               new AppSalesData {Reported = DateTime.Now.AddMonths(-6), FeedbackCount = _Randomize(33), InstallCount = _Randomize(2301), LicensedUserCount = _Randomize(430), Revenue = _Randomize(45030)},
                                               new AppSalesData {Reported = DateTime.Now.AddMonths(-5), FeedbackCount = _Randomize(22), InstallCount = _Randomize(1890), LicensedUserCount = _Randomize(449), Revenue = _Randomize(46010)},
                                               new AppSalesData {Reported = DateTime.Now.AddMonths(-4), FeedbackCount = _Randomize(56), InstallCount = _Randomize(1433), LicensedUserCount = _Randomize(556), Revenue = _Randomize(47880)},
                                               new AppSalesData {Reported = DateTime.Now.AddMonths(-3), FeedbackCount = _Randomize(44), InstallCount = _Randomize(887), LicensedUserCount = _Randomize(643), Revenue = _Randomize(45019)},
                                               new AppSalesData {Reported = DateTime.Now.AddMonths(-2), FeedbackCount = _Randomize(99), InstallCount = _Randomize(3657), LicensedUserCount = _Randomize(542), Revenue = _Randomize(48021)},
                                               new AppSalesData {Reported = DateTime.Now.AddMonths(-1), FeedbackCount = _Randomize(21), InstallCount = _Randomize(14500), LicensedUserCount = _Randomize(498), Revenue = _Randomize(49099)}
                                           };

#endif

                    #endregion

                    var ani = new Animation { BeginTime = new TimeSpan(0, 0, 1), Duration = new Duration(new TimeSpan(0, 0, 5)) };

                    // Generate a random color
                    byte red = Convert.ToByte(rgbRand.Next(0, 255));
                    byte green = Convert.ToByte(rgbRand.Next(0, 255));
                    byte blue = Convert.ToByte(rgbRand.Next(0, 255));

                    // Add product sales data to chart
                    var combinedRevOverTime = new Series { Animation = ani, Label = product.Name, ChartType = ChartType.Line, StrokeThickness = 3, Fill = new SolidColorBrush(Color.FromRgb(red, green, blue)) };
                    var combinedInstallsOverTime = new Series { Animation = ani, Label = product.Name, ChartType = ChartType.Line, StrokeThickness = 3, Fill = new SolidColorBrush(Color.FromRgb(red, green, blue)) };
                    foreach (AppSalesData asd in aps.AppSalesData)
                    {
                        string label = asd.Reported.ToString("M/yy");
                        combinedRevOverTime.DataPoints.Add(new DataPoint { Label = label, Value = Convert.ToDouble(asd.Revenue) });
                        combinedInstallsOverTime.DataPoints.Add(new DataPoint { Label = label, Value = asd.InstallCount });
                    }

                    CombinedRevenueOverTimeChart.Series.Add(combinedRevOverTime);
                    CombinedInstallationsOverTimeChart.Series.Add(combinedInstallsOverTime);

                    _AddAppStatusRow(new AppStatusRow(aps, ctr == products.Count - 1), ref rowIndex);
                    ++ctr;
                }

                Window.Height = 650 + rowIndex * 30;

            }
            catch (Exception e)
            {
            }
            finally
            {
                this.Cursor = lastCursor;
            }
        }

        private int _Randomize(int p)
        {
            if (r == null) r = new Random(DateTime.Now.Second);
            return r.Next(p - p / 2, p + p / 2);
        }

        private void Dashboard_Closed(object sender, EventArgs e)
        {
            App.Current.Shutdown();
        }

        private List<AppStatusRow> addedRows = new List<AppStatusRow>();

        private void _AddAppStatusRow(AppStatusRow row, ref int rowIndex)
        {
            row.AppNameClicked += ProductTableAppNameClicked;
            AppStatusGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(30) });
            Grid.SetRow(row, ++rowIndex);
            Grid.SetColumnSpan(row, 12);
            AppStatusGrid.Children.Add(row);
            addedRows.Add(row);
        }

        private void ProductTableAppNameClicked(object sender, EventArgs e)
        {
            var asr = sender as AppStatusRow;
            if (asr != null && asr.AppStatus.ID != Guid.Empty)
            {
                var usageWindow = new AppUsage(this, asr.AppStatus) { Left = Left, Top = Top };
                foreach (object window in Application.Current.Windows)
                {
                    ((Window)window).Hide();
                }
                usageWindow.Show();
            }
        }

        private void SignOutButton_Click(object sender, RoutedEventArgs e)
        {
            var loginWindow = new Login { Left = Left, Top = Top };
            foreach (object window in Application.Current.Windows)
            {
                ((Window)window).Hide();
            }
            loginWindow.Show();
        }

        private void RegisterAppButton_Click(object sender, RoutedEventArgs e)
        {
            if (overlay == null)
            {
                overlay = new Border { VerticalAlignment = VerticalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Center, Width = Width, Height = Height, Opacity = .4 };
                overlay.Background = new SolidColorBrush(Colors.Black);
                overlay.MouseUp += OverlayMouseDown;
                LayoutRoot.Children.Add(overlay);
            }
            overlay.Visibility = Visibility.Visible;

            if (newProductReg == null)
            {
                newProductReg = new Products();
                LayoutRoot.Children.Add(newProductReg);
            }
            newProductReg.Visibility = Visibility.Visible;
        }

        private void OverlayMouseDown(object sender, MouseButtonEventArgs e)
        {
            overlay.Visibility = Visibility.Hidden;
            newProductReg.Visibility = Visibility.Hidden;
            ReloadProductTable();
        }
    }

    public class AppSalesData : DependencyObject
    {
        public static readonly DependencyProperty FeedbackCountProperty = DependencyProperty.Register("FeedbackCount", typeof(int), typeof(AppStatusRow), new UIPropertyMetadata(0));
        public static readonly DependencyProperty InstallCountProperty = DependencyProperty.Register("InstallCount", typeof(int), typeof(AppStatusRow), new UIPropertyMetadata(0));
        public static readonly DependencyProperty LicensedUserCountProperty = DependencyProperty.Register("LicensedUserCount", typeof(int), typeof(AppStatusRow), new UIPropertyMetadata(0));
        public static readonly DependencyProperty ReportedProperty = DependencyProperty.Register("Reported", typeof(DateTime), typeof(AppStatusRow), new UIPropertyMetadata(DateTime.MinValue));
        public static readonly DependencyProperty RevenueProperty = DependencyProperty.Register("Revenue", typeof(decimal), typeof(AppStatusRow), new UIPropertyMetadata(365.90m));

        public DateTime Reported
        {
            get { return (DateTime)GetValue(ReportedProperty); }
            set { SetValue(ReportedProperty, value); }
        }

        public decimal Revenue
        {
            get { return (decimal)GetValue(RevenueProperty); }
            set { SetValue(RevenueProperty, value); }
        }


        public int FeedbackCount
        {
            get { return (int)GetValue(FeedbackCountProperty); }
            set { SetValue(FeedbackCountProperty, value); }
        }

        public int LicensedUserCount
        {
            get { return (int)GetValue(LicensedUserCountProperty); }
            set { SetValue(LicensedUserCountProperty, value); }
        }

        public int InstallCount
        {
            get { return (int)GetValue(InstallCountProperty); }
            set { SetValue(InstallCountProperty, value); }
        }
    }

    public class AppStatus : DependencyObject
    {
        public static readonly DependencyProperty AppNameProperty = DependencyProperty.Register("AppName", typeof(string), typeof(AppStatusRow), new UIPropertyMetadata("Application Name"));

        public static readonly DependencyProperty AppSalesDataProperty = DependencyProperty.Register("AppSalesData", typeof(List<AppSalesData>), typeof(AppStatusRow), new UIPropertyMetadata(new List<AppSalesData> { }));

        public static readonly DependencyProperty FeedBackProperty = DependencyProperty.Register("FeedBack", typeof(int), typeof(AppStatusRow), new UIPropertyMetadata(0));

        public static readonly DependencyProperty IDProperty = DependencyProperty.Register("ID", typeof(Guid), typeof(AppStatusRow), new UIPropertyMetadata(Guid.Empty));

        public static readonly DependencyProperty LicensedUsersProperty = DependencyProperty.Register("LicensedUsers", typeof(int), typeof(AppStatusRow), new UIPropertyMetadata(0));

        public static readonly DependencyProperty RecentErrProperty = DependencyProperty.Register("RecentErr", typeof(int), typeof(AppStatusRow), new UIPropertyMetadata(0));

        public static readonly DependencyProperty RecentInstallsProperty = DependencyProperty.Register("RecentInstalls", typeof(int), typeof(AppStatusRow), new UIPropertyMetadata(0));

        public static readonly DependencyProperty RecentRevProperty = DependencyProperty.Register("RecentRev", typeof(decimal), typeof(AppStatusRow), new FrameworkPropertyMetadata(34.56m));

        public static readonly DependencyProperty TotalErrProperty = DependencyProperty.Register("TotalErr", typeof(int), typeof(AppStatusRow), new UIPropertyMetadata(0));

        public static readonly DependencyProperty TotalInstallsProperty = DependencyProperty.Register("TotalInstalls", typeof(int), typeof(AppStatusRow), new UIPropertyMetadata(0));

        public static readonly DependencyProperty TotalRevProperty = DependencyProperty.Register("TotalRev", typeof(decimal), typeof(AppStatusRow), new UIPropertyMetadata(78.90m));

        public static readonly DependencyProperty UpcomingLicExpProperty = DependencyProperty.Register("UpcomingLicExp", typeof(int), typeof(AppStatusRow), new UIPropertyMetadata(0));

        public static readonly DependencyProperty UpcomingTrialExpProperty = DependencyProperty.Register("UpcomingTrialExp", typeof(int), typeof(AppStatusRow), new UIPropertyMetadata(0));

        public List<AppSalesData> AppSalesData
        {
            get { return (List<AppSalesData>)GetValue(AppSalesDataProperty); }
            set { SetValue(AppSalesDataProperty, value); }
        }

        public Guid ID
        {
            get { return (Guid)GetValue(IDProperty); }
            set { SetValue(IDProperty, value); }
        }

        public string AppName
        {
            get { return (string)GetValue(AppNameProperty); }
            set { SetValue(AppNameProperty, value); }
        }

        public int FeedBack
        {
            get { return (int)GetValue(FeedBackProperty); }
            set { SetValue(FeedBackProperty, value); }
        }

        public decimal RecentRev
        {
            get { return (decimal)GetValue(RecentRevProperty); }
            set { SetValue(RecentRevProperty, value); }
        }

        public decimal TotalRev
        {
            get { return (decimal)GetValue(TotalRevProperty); }
            set { SetValue(TotalRevProperty, value); }
        }


        public int LicensedUsers
        {
            get { return (int)GetValue(LicensedUsersProperty); }
            set { SetValue(LicensedUsersProperty, value); }
        }

        public int RecentInstalls
        {
            get { return (int)GetValue(RecentInstallsProperty); }
            set { SetValue(RecentInstallsProperty, value); }
        }

        public int TotalInstalls
        {
            get { return (int)GetValue(TotalInstallsProperty); }
            set { SetValue(TotalInstallsProperty, value); }
        }

        public int UpcomingTrialExp
        {
            get { return (int)GetValue(UpcomingTrialExpProperty); }
            set { SetValue(UpcomingTrialExpProperty, value); }
        }

        public int UpcomingLicExp
        {
            get { return (int)GetValue(UpcomingLicExpProperty); }
            set { SetValue(UpcomingLicExpProperty, value); }
        }

        public int RecentErr
        {
            get { return (int)GetValue(RecentErrProperty); }
            set { SetValue(RecentErrProperty, value); }
        }

        public int TotalErr
        {
            get { return (int)GetValue(TotalErrProperty); }
            set { SetValue(TotalErrProperty, value); }
        }
    }
}